/*
 * Borovicska Szglab4 2011
 * @package circuit1
 */
package circuit1;

import java.io.*;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import javax.swing.Timer;

/**
 * Controller
 * @author Gergely Hernesz <herneszg@gmail.com>
 */
public class Controller implements Observer{

    private YamlAdapter adapter;
    private Circuit circuit;
    private View view;
    Timer timer;

    /**
     * Program belepesi pont
     * @param args 
     */
    public static void main(String[] args) {
        Controller c = new Controller();
        ArrayList<Wire> al = new ArrayList<Wire>();
        Wire w1 = new Wire();
        w1.setValue(true);
        al.add(w1);
        w1 = new Wire();
        w1 = al.get(0);
        al.add(w1);
        //System.out.println("w2: " + al.get(1).getValue());
        //System.out.println("w1: " + al.get(0).getValue());
        al.get(1).setValue(false);
        //System.out.println("w2: " + al.get(1).getValue());
        //System.out.println("w1: " + al.get(0).getValue());
    }

    /**
     * Konstruktor, ami input fajl alapjan elinditja a mukodest
     * @param inputFile 
     */
    public Controller() {
        view = new View(this);
        timer = new Timer(200, view);
    }
    
    public void update(Observable observable, Object object){
        if (object.equals("load")) {
            String path = view.getPath();
            timer.stop();
            try {
                view.tf.setText(path + " loaded");
                adapter = new YamlAdapter(path);
                tickAll(50);
            } catch (Exception e) {
                System.err.println("\nError: " + e);
            }
            createModel();
            view.draw();
            for(Composite cmp : circuit.getCompositeElements()){
        }
        }
        if (object.equals("step")) {
            view.tf.setText("Generator signal stepped");
            tickAll(50);
            view.reDraw();
        }
        if (object.equals("stepon")) {
            view.tf.setText("Generator autostep turned ON");
            timer.start();
            }
        if (object.equals("stepoff")) {
            view.tf.setText("Generator autostep turned OFF");
            timer.stop();
        }    
        if (object.equals("switch")) {            
            view.tf.setText("Switch toggled");
            tickAll(50);
            view.reDraw();
        }
    }
    
    public void createModel(){
        circuit = adapter.getCircuit();
    }
    
    public Circuit getModel(){
        return circuit;
    }

    /**
     * Az inputfile egy sorabol visszaadja a parancsot
     * @param line
     * @return 
     */
    private String getCommandByInputLine(String line) {
        String[] cmds = line.split("\\s+");
        return cmds[0];
    }

    /**
     * Az inputfile egy sorabol visszaadja a parancs parametereit
     * @param line
     * @return 
     */
    private String[] getCmdParametersByInputLine(String line) {
        String[] cmds = line.split("\\s+");
        return java.util.Arrays.copyOfRange(cmds, 1, cmds.length);
    }

    /**
     * Lekezeli, majd vegrehajtja a parancsot
     * @param cmd
     * @param params 
     */
    private void handleCmd(String cmd, String[] params) {
        if (cmd.equals("loadcircuit")) {
            adapter = new YamlAdapter(params[0]);
        } else if (cmd.equals("exit")) {
            //System.out.println("The program is exiting");
            System.exit(0);
        } else if (cmd.equals("tick")) {
            tickAll(Integer.valueOf(params[0]));
        } else if (cmd.equals("switch")) {
            Switch sw = (Switch) adapter.getCircuit().getElementById(params[0]);
            if (sw == null) {
                //System.out.println("Invalid paramter " + params[0]);
                //System.out.println("The program is exiting");
                System.exit(1);
            }
            if (params[1].equals("on")) {
                sw.on();
            } else if (params[1].equals("off")) {
                sw.off();
            } else if (params[1].equals("toggle")) {
                sw.act();
            } else {
                //System.out.println("Invalid command parameter");
            }
        } else if (cmd.equals("stepgenerator")) {
            adapter.getCircuit().getElementById(params[0]).act();
        } else {
            if (cmd.length() > 0) {
                //System.out.println("Invalid command " + cmd);
            }
        }
    }

    /**
     * Minden aramkorben levo elemet megbok d-szer
     * @param int d 
     */
    public void tickAll(int d) {
        StabilityObserver o = adapter.getCircuit().getStabilityObserver();
        int i = 0;
        boolean s1 = false, s2 = false;
        for (i = 1; i <= d; i++) {
            //System.out.println("IIIIIIIIIIIIIIIII : " + i);
            s2 = tickAllCompositesElements(adapter.getCircuit().getCompositeElements());
            s1 = tickCircuitElements(adapter.getCircuit());
            if (s1 & s2)
                break;
        }
        display();
        if (i < d) {
            view.tf.setText("Circuit is stable");
        } else {
            view.tf.setText("Circuit is unstable");
        }
    }

    /**
     * Megboki az aramkor elemeit
     * @param c
     * @return 
     */
    private boolean tickCircuitElements(Circuit c) {
        c.getStabilityObserver().prodAllElements(c.getElements());
        return c.getStabilityObserver().count();
    }

    /**
     * Megboki az osszes kompozit elemeit
     * @param composites
     * @return 
     */
    private boolean tickAllCompositesElements(ArrayList<Composite> composites) {
        //System.out.println("TICK ALL ::::::::::::::::");
        boolean[] b = new boolean[composites.size()];
        int i = 0;
        for (Composite c : composites) {
            //System.out.println("ticked " + c.getName());
            c.getStabilityObserver().prodAllElements(c.getElements());
            b[i++] = c.getStabilityObserver().count();
        }
        for (i--; i > 0; i--) {
            if (b[i] == false) {
                return false;
            }
        }
        return true;
    }

    /**
     * Megjeleniti a kijelzok ertekeit
     */
    private void display() {
        for (IElement e : adapter.getCircuit().getElements()) {
            e.show();
        }
    }

    /**
     * Kimeneti fajlt kezelo osztaly
     */
    /*private static class OutputHandler extends PrintStream {

        private String outputFile;

        public OutputHandler(String outputFile) {
            super(System.out);
            this.outputFile = outputFile;
            clearFile();
        }*/

        /**
         * Stdout-ra iras elott lementjuk fajlba a kimenetet
         * @param String s 
         */
        /*@Override
        public void println(String s) {
            try {
                FileWriter fw = new FileWriter(outputFile, true);
                fw.write(s + "\n");
                fw.close();
            } catch (Exception e) {
                //System.out.print("");
            }
            getOut().println(s);
        }
        
        @Override
        public void print(String s) {
            try {
                FileWriter fw = new FileWriter(outputFile, true);
                fw.write(s);
                fw.close();
            } catch (Exception e) {
                //System.out.print("");
            }
            getOut().println(s);
        }*/

        /**
         * Visszaadja a PrintStream-et
         * @return PrintStream
         */
        /*private PrintStream getOut() {
            return ((PrintStream) out);
        }/*
        
        /**
         * Inicializalaskor torli a kimeneti fajl tartalmat
         */
        /*private void clearFile() {
            try {
                FileWriter fw = new FileWriter(outputFile);
                fw.write("");
                fw.close();
            } catch (Exception e) {
            }
        }
    }*/
}
